#ifndef VENUS_GEOMETRY_VECTOR4_H
#define VENUS_GEOMETRY_VECTOR4_H

#include "common/venus.h"
#include "common/math.h"

namespace venus {
  class Vector4 {
  public:
    Vector4(float r, float g, float b) : r(r), g(g), b(b), a( 0 ) { }

    Vector4() : x( 0.0f ), y( 0.0f ), z( 0.0f ), w( 0.0f ) {}

    Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}

    float Length() const { return (float)sqrt( SqrLength() ); }

    float SqrLength() const { return x * x + y * y + z * z + w * w; }

    Vector4 operator+(const Vector4& v) const {
      return Vector4(x + v.x, y + v.y, z + v.z, w + v.w);
    }
 
    Vector4& operator+=(const Vector4& v) { 
      x += v.x; y += v.y; z += v.z; w += v.w; return *this; 
    }

    Vector4 operator+(float f) const { return Vector4(x+f, y+f, z+f, w+f); } 

    Vector4& operator+=(float f) { x+=f; y+=f; z+=f; w+=f; return *this; }

    Vector4 operator-(const Vector4& v) const {
      return Vector4(x - v.x, y - v.y, z - v.z, w - v.w);
    }

    Vector4& operator-=(const Vector4& v) { 
      x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this;
    }

    Vector4 operator-(float f) const { return Vector4(x-f, y-f, z-f, w-f); } 

    Vector4& operator-=(float f) { x-=f; y-=f; z-=f; w-=f; return *this; }

    Vector4 operator*(float f) const { return Vector4(x*f, y*f, z*f, w*f); }

    Vector4& operator*=(float f) { x*=f; y*=f; z*=f; w*=f; return *this; }

    Vector4 operator*(const Vector4& v) const {
      return Vector4(x * v.x, y * v.y, z * v.z, w * v.w);
    }
 
    Vector4& operator*=(const Vector4& v) {
      x *= v.x; y *= v.y; z *= v.z;  w *= v.w; return *this;
    }

    Vector4 operator/(float f) const { return *this * (1 / f); }

    Vector4& operator/=(float f) { return *this *= (1 / f); }

    Vector4 operator-() const { return Vector4(-x, -y, -z, -w); }

    float operator[]( const int i ) const { return cell[i]; }

    float& operator[]( const int i ) { return cell[i]; }

    float* ptr() { return &x; }

    const float* ptr() const { return &x; }

    union {
      struct { float x, y, z, w; };
      struct { float r, g, b, a; };
      struct { float cell[4]; };
    };
  };

  inline Vector4 operator+(float f, const Vector4& v) { return v + f; }

  inline Vector4 operator*(float f, const Vector4& v) { return v * f; }

  inline float Dot(const Vector4& v1, const Vector4& v2) {
    return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w; 
  }
  
  inline Vector4 Normalize(const Vector4& v) { return v / v.Length(); } 

  typedef Vector4 Color;
}

#endif//VENUS_GEOMETRY_VECTOR4_H
